package edu.maping.easy.model;

import java.util.ArrayList;
import java.util.List;

import processing.core.PApplet;

public class PolygonThingBezier extends PolygonThing {

	public ArrayList<Point[]> extraVertexs = new ArrayList<Point[]>();
	public ArrayList<Point> realVertexs = new ArrayList<Point>();
	private final static int STEPS = 10;
	private PApplet pApplet;

	public PolygonThingBezier(PApplet pApplet) {
		this.pApplet = pApplet;
	}

	public void addPoint(Point point) {
		Point[] controlPoints = new Point[2];
		controlPoints[0] = new Point(point.x - 10, point.y - 15);
		controlPoints[1] = new Point(point.x + 10, point.y - 15);
		addPoint(point, controlPoints);
	}

	public void addPoint(Point point, Point[] controlPoints) {
		super.addPoint(point);
		if (extraVertexs.size() == 0) {
			extraVertexs.add(controlPoints);
			point.first = true;
			extraVertexs.add(extraVertexs.size() - 1, controlPoints);
		} else {
			extraVertexs.add(extraVertexs.size() - 1, controlPoints);
		}
	}

	public void draw(PApplet applet) {

		if (vertex.isEmpty())
			return;

		// applet.noFill();
		applet.beginShape();
		Point pLast = vertex.get(0);
		// applet.ellipse(pLast.x, pLast.y, 25, 25);
		applet.vertex(pLast.x, pLast.y);
		for (int i = 1; i < vertex.size(); i++) {
			Point p = vertex.get(i);
			Point[] cps = extraVertexs.get(i);
			applet.bezierVertex(cps[0].x, cps[0].y, cps[1].x, cps[1].y, p.x,
					p.y);
			pLast = p;
		}
		applet.endShape();
	}

	public void refresh() {
		if (vertex.isEmpty())
			return;

		realVertexs.clear();

		Point pLast = vertex.get(0);
		for (int i = 1; i < vertex.size(); i++) {
			Point p = vertex.get(i);
			Point[] cps = extraVertexs.get(i);
			// pApplet.bezier(pLast.x, pLast.y, cps[0].x, cps[0].y, cps[1].x,
			// cps[1].y, p.x, p.y);

			// applet.fill(255);
			for (int j = 0; j <= STEPS; j++) {
				float t = j / (float) STEPS;
				float x = pApplet.bezierPoint(pLast.x, cps[0].x, cps[1].x, p.x,
						t);
				float y = pApplet.bezierPoint(pLast.y, cps[0].y, cps[1].y, p.y,
						t);

				realVertexs.add(new Point((int) x, (int) y));

				// pApplet.ellipse(x, y, 5, 5);
			}
			pLast = p;
		}
	}

	public void editDraw(PApplet applet) {

		// applet.beginShape();
		// applet.vertex(30, 20);
		// applet.bezierVertex(80, 0, 80, 75, 30, 75);
		// applet.bezierVertex(50, 80, 60, 25, 30, 20);
		// applet.endShape();

		applet.strokeWeight(1);
		applet.noFill();
		draw(applet);

		if (vertex.isEmpty())
			return;
		Point pLast = vertex.get(0);
		applet.ellipse(pLast.x, pLast.y, 25, 25);

		for (int i = 1; i < vertex.size(); i++) {
			Point p = vertex.get(i);
			Point[] cps = extraVertexs.get(i);
			applet.stroke(0, 255, 0);
			applet.ellipse(p.x, p.y, 25, 25);

			applet.stroke(0, 255, 255);
			applet.ellipse(cps[0].x, cps[0].y, 15, 15);
			applet.ellipse(cps[1].x, cps[1].y, 15, 15);

			applet.line(p.x, p.y, cps[0].x, cps[0].y);
			applet.line(p.x, p.y, cps[1].x, cps[1].y);
			// applet.vertex(p.x, p.y);
			// applet.line(pLast.x, pLast.y, p.x, p.y);
			pLast = p;
		}
	}

	@Override
	public Point getPoint(int x, int y) {
		Point point = super.getPoint(x, y);
		if (point == null) {
			for (int i = 1; i < extraVertexs.size(); i++) {
				Point[] pp = extraVertexs.get(i);

				if (pp[0].isThisPoint(x, y)) {
					point = pp[0];
					break;
				}

				if (pp[1].isThisPoint(x, y)) {
					point = pp[1];
					break;
				}
			}
		}
		return point;
	}

	@Override
	public Thing copy() {

		PolygonThingBezier thing = new PolygonThingBezier(pApplet);

		copy(thing);

		ArrayList<Point[]> news = new ArrayList<Point[]>();
		for (int i = 0; i < extraVertexs.size(); i++) {
			Point[] pointt = extraVertexs.get(i);
			Point point1 = pointt[0].copyPoint();
			Point point2 = pointt[1].copyPoint();
			Point[] pointtNew = new Point[2];
			pointtNew[0] = point1;
			pointtNew[1] = point2;
			news.add(pointtNew);
		}
		thing.extraVertexs = news;

		return thing;
	}

	public void moveXY(int x, int y) {
		// No actualizo el primero, porque es la misma instancia que el último
		super.moveXY(x, y);
		this.move(x, y);
		for (int i = 1; i < extraVertexs.size(); i++) {
			extraVertexs.get(i)[0].move(x, y);
			extraVertexs.get(i)[1].move(x, y);
		}
		refresh();
	}

	public boolean contains(Point p0) {
		return contains(p0, realVertexs);
	}

}
